<template>
  <el-row :gutter="24" class="panel-group">
    <el-col
      v-for="card in cards"
      :key="card.key"
      :xs="24"
      :sm="12"
      :lg="6"
      class="card-panel-col"
    >
      <el-card
        shadow="hover"
        class="card-panel"
        :body-style="{ padding: '20px 20px 12px' }"
        v-loading="loading"
      >
        <div class="card-header" :style="{ '--accent-color': card.color || '#409eff' }">
          <div class="card-icon" :style="resolveIconStyle(card)">
            <svg-icon :icon-class="card.icon || 'dashboard'" class-name="card-panel-icon" />
          </div>
          <div class="card-title-group">
            <span class="card-title">{{ card.title }}</span>
            <span class="card-subtitle" v-if="card.subtitle">{{ card.subtitle }}</span>
          </div>
        </div>
        <div class="card-metrics">
          <div class="card-value">
            <count-to
              v-if="!loading"
              class="card-value-number"
              :start-val="0"
              :end-val="Number(card.value) || 0"
              :decimals="card.decimals || 0"
              :duration="400"
            />
            <span v-else class="card-value-number">{{ formatNumeric(card.value, card.decimals) }}</span>
            <span class="card-unit">{{ card.suffix || card.unit || '' }}</span>
          </div>
          <ul v-if="hasBreakdown(card)" class="card-breakdown">
            <li v-for="item in card.breakdown" :key="item.label" class="card-breakdown-item">
              <span class="label">{{ item.label }}</span>
              <span class="value">
                {{ formatNumeric(item.value, item.decimals ?? card.decimals) }}{{ item.suffix || card.suffix || card.unit || '' }}
              </span>
            </li>
          </ul>
        </div>
      </el-card>
    </el-col>
  </el-row>
</template>

<script>
import CountTo from "vue-count-to";

export default {
  components: {
    CountTo,
  },
  props: {
    cards: {
      type: Array,
      default: () => [],
    },
    loading: {
      type: Boolean,
      default: false,
    },
  },
  methods: {
    hasBreakdown(card) {
      return card && Array.isArray(card.breakdown) && card.breakdown.length > 0;
    },
    resolveIconStyle(card) {
      const color = card && card.color ? card.color : "#409eff";
      return {
        color,
        backgroundColor: this.addOpacity(color, 0.12),
      };
    },
    addOpacity(color, opacity) {
      if (!color) return `rgba(64, 158, 255, ${opacity})`;
      if (color.startsWith("#")) {
        const hex = color.slice(1);
        const bigint = parseInt(hex.length === 3 ? hex.replace(/(.)/g, "$1$1") : hex, 16);
        const r = (bigint >> 16) & 255;
        const g = (bigint >> 8) & 255;
        const b = bigint & 255;
        return `rgba(${r}, ${g}, ${b}, ${opacity})`;
      }
      if (color.startsWith("rgb")) {
        return color.replace(/rgba?\(([^)]+)\)/, (match, group) => {
          const parts = group.split(',').map((item) => item.trim());
          const [r, g, b] = parts;
          return `rgba(${r}, ${g}, ${b}, ${opacity})`;
        });
      }
      return `rgba(64, 158, 255, ${opacity})`;
    },
    formatNumeric(value, decimals = 0) {
      if (value === null || value === undefined || Number.isNaN(Number(value))) {
        return "0";
      }
      const factor = Math.pow(10, decimals);
      const normalized = Math.round(Number(value) * factor) / factor;
      return decimals > 0
        ? normalized.toFixed(decimals)
        : Math.round(normalized).toLocaleString();
    },
  },
};
</script>

<style lang="scss" scoped>
.panel-group {
  margin-top: 18px;

  .card-panel-col {
    margin-bottom: 24px;
  }

  .card-panel {
    border: 1px solid #f1f2f5;
    border-radius: 12px;
    min-height: 160px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;

    .card-header {
      display: flex;
      align-items: center;
      margin-bottom: 16px;

      .card-icon {
        width: 48px;
        height: 48px;
        border-radius: 12px;
        background: rgba(64, 158, 255, 0.12);
        display: flex;
        align-items: center;
        justify-content: center;
        margin-right: 16px;
        color: var(--accent-color);

        .card-panel-icon {
          font-size: 28px;
        }
      }

      .card-title-group {
        display: flex;
        flex-direction: column;
        gap: 4px;

        .card-title {
          font-size: 18px;
          font-weight: 600;
          color: #303133;
        }

        .card-subtitle {
          font-size: 13px;
          color: #909399;
        }
      }
    }

    .card-metrics {
      .card-value {
        display: flex;
        align-items: baseline;
        gap: 4px;
        margin-bottom: 12px;

        .card-value-number {
          font-size: 28px;
          font-weight: 600;
          color: #303133;
        }

        .card-unit {
          font-size: 14px;
          color: #909399;
        }
      }

      .card-breakdown {
        list-style: none;
        padding: 0;
        margin: 0;
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
        gap: 6px 12px;

        .card-breakdown-item {
          display: flex;
          justify-content: space-between;
          font-size: 13px;
          color: #606266;

          .label {
            color: #909399;
          }
        }
      }
    }
  }
}

@media (max-width: 768px) {
  .panel-group {
    .card-panel {
      min-height: auto;

      .card-breakdown {
        grid-template-columns: 1fr;
      }
    }
  }
}
</style>
